﻿using Microsoft.Xna.Framework;

namespace DestructibleTextureDemo
{
    /// <summary> 
    /// Represents a 2D circle. 
    /// </summary> 
    public struct Circle
    {

        /// <summary> 
        /// Center position of the circle. 
        /// </summary> 
        private Vector2 _center;

        /// <summary> 
        /// Radius of the circle. 
        /// </summary> 
        private readonly float _radius;

        /// <summary>
        /// Radius times Radius of the circle 
        /// </summary>
        private readonly float _radiusSquared;

        public Vector2 Center { get { return _center; } }
        public float Radius { get { return _radius; } }
        public float X { get { return _center.X; } }
        public float Y { get { return _center.Y; } }

        /// <summary> 
        /// Constructs a new circle. 
        /// </summary> 
        public Circle(Vector2 position, float radius)
        {
            _center = position;
            _radius = radius;
            _radiusSquared = radius * _radius;
        }

        /// <summary>
        /// Determinates if a Point is intersects the circle
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public bool Intersects(Point point)
        {

            float X = point.X - _center.X;
            float Y = point.Y - _center.Y;

            return (X * X + Y * Y == _radiusSquared);
        }

        /// <summary> 
        /// Determines if a circle intersects a rectangle. 
        /// </summary> 
        /// <returns>True if the circle and rectangle overlap. False otherwise.</returns> 
        public bool Intersects(Rectangle rectangle)
        {
            Vector2 v = new Vector2(MathHelper.Clamp(_center.X, rectangle.Left, rectangle.Right),
                                    MathHelper.Clamp(_center.Y, rectangle.Top, rectangle.Bottom));

            Vector2 direction = _center - v;
            float distanceSquared = direction.LengthSquared();

            return ((distanceSquared > 0) && (distanceSquared < _radiusSquared));
        }

        /// <summary>
        /// Determinates if a Point is inside a the circle
        /// </summary>
        /// <param name="point"></param>
        /// <returns></returns>
        public bool Contains(Point point)
        {
            float X = point.X - _center.X;
            float Y = point.Y - _center.Y;

            return (X * X + Y * Y <= _radiusSquared);
        }

        /// <summary> 
        /// Determines if a circle intersects a rectangle. 
        /// </summary> 
        /// <returns>True if the circle is inside the rectangle or intersects. False otherwise.</returns> 
        public bool Constains(Rectangle rectangle)
        {
            Vector2 v = new Vector2(MathHelper.Clamp(_center.X, rectangle.Left, rectangle.Right),
                                    MathHelper.Clamp(_center.Y, rectangle.Top, rectangle.Bottom));

            Vector2 direction = _center - v;
            float distanceSquared = direction.LengthSquared();

            return ((distanceSquared >= 0) && (distanceSquared <= _radiusSquared));
        }
    }
}